#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include <functional>
#include "Socket.hpp"
#include "InetAddr.hpp"
class Request
{
public:
    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper)
    {
    }
    Request() {}
    ~Request() {}
    // 序列化与反序列化
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    bool deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader read;
        bool ok = read.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asUInt();
        }

        return ok;
    }
    int X()
    {
        return _x;
    }
    int Y()
    {
        return _y;
    }
    char Oper()
    {
        return _oper;
    }

private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response() {}
    ~Response() {}
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        std::string ss = writer.write(root);
        return ss;
    }
    bool deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader read;
        bool ok = read.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
    void SetResult(int n)
    {
        _result = n;
    }
    void Setcode(int ret)
    {
        _code = ret;
    }
    void ShowResult()
    {
        std::cout<<_result<<std::endl;
    }
private:
    int _result;
    int _code;
};

const std::string sep = "/r/n";
using func1_t = std::function<Response(Request &req)>;
class Protocol
{
public:
    Protocol(func1_t func) : _func(func)
    {
    }
    Protocol()
    {
    }
    ~Protocol()
    {
    }
    // 添加报头与标识符
    std::string Encode(std::string &jsonstr)
    {
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    // 分析处理字符串确保读到一个完整的报文
    bool Decode(std::string &buffer, std::string *str)
    {
        int pos = buffer.find(sep);
        if (pos == std::string::npos)
        {
            // 太短了，报文不完整让调用方继续读
            return false;
        }
        std::string page_len_str = buffer.substr(0, pos);
        int page_len_int = std::stoi(page_len_str);

        // 此时拿到了报文的长度，判断后续有没有完整报文：
        int target_len = page_len_str.size() + page_len_int + 2 * sep.size();
        if (buffer.size() < target_len)
        {
            // 太短了，报文不完整让调用方继续读
            return false;
        }
        // 存在完整报文，处理提取报文主体让输出型参数带出去
        *str = buffer.substr(pos + sep.size(), page_len_int);
        // 删除处理过的报文
        buffer.erase(0, target_len);
        return true;
    }

    // 当服务器Accept成功之后会返回一个TCP套接字和客户端消息并传递到协议层来处理：
    void GetRequest(std::shared_ptr<Socket> ptr, InetAddr client)
    {
        // 进来先读取
        std::string buffer_quenue;
        while (1)
        {
            int ret = ptr->Recv(&buffer_quenue);
            if (ret > 0)
            {
                // 读成功了，分析读到的消息
                // 首先判断报文是否完整：
                std::string json_package;
                bool ok = Decode(buffer_quenue, &json_package);
                if (!ok)
                {
                    continue;
                }
                else
                {
                    // 获得了一个完整的报文：
                    Request req;
                    bool n = req.deserialize(json_package);
                    if (n > 0)
                    {
                        // 获得了一个完整的请求，包含了x,y,运算符
                        // 计算运算结果，并构建response发给客户端
                        Response resp = _func(req);
                        // 进行序列化并添加报头：
                        std::string json_str = resp.Serialize();
                        std::string send_str = Encode(json_str);
                        // 发送：
                        ptr->Send(send_str);
                    }
                }
            }
            else if (ret == 0)
            {
                // 客户端退出0
                break;
            }
            else
            {
                // 读失败了继续读
                break;
            }
        }
    }
    // 客户端调用接受并处理服务端发送过来的结果报文
    bool GetResponse(std::shared_ptr<Socket> ptr,std::string* inbuffer,Response* res)
    {
        //这里需要外面传进来一个缓冲区，否则临时缓冲区读多的话函数调用结束数据就丢失了
        while (1)
        {
            int ret = ptr->Recv(inbuffer);
            if (ret > 0)
            {
                std::string json_package;
                bool ok = Decode(*inbuffer, &json_package);
                if (!ok)
                {
                    continue;
                }
                //走到这里说明提取到了一个完整的报文在json_package中
                res->deserialize(json_package);
                return true;
            }
            else if (ret == 0)
            {
                LOG(LogLevel::INFO) << "server exit!!";
                return true;
            }
            else
            {
                LOG(LogLevel::ERROR) << "recv fail!";
                return false;
            }
        }
    }
    std::string BuildRequest(int x, int y, char oper)
    {
        Request req(x, y, oper);
        // 进行序列化：
        std::string json_str = req.Serialize();
        // 添加报头
        std::string request = Encode(json_str);
        return request;
    }

private:
    // 回调到上层应用层
    func1_t _func;
};